package stack;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author 老顾
 * @title: ArrayDeque
 * @projectName java-restudy
 * @email: 1437594522@qq.com
 * @date 2022/11/7 7:21
 */
public class ArrayDeque<E> implements Deque<E>{

    private final Logger logger = LoggerFactory.getLogger(ArrayDeque.class);

    transient Object[] elements;

    transient int head;

    transient int tail;

    public ArrayDeque(){
        elements = new Object[2];
    }

    public void doubleCapacity() {
        assert head == tail;
        int p = head;
        int n = elements.length;
        int r = n - p;
        int newCapacity = n << 1;
        if (newCapacity < 0){
            System.out.println("抱歉，队列太大了");
        }
        Object[] a = new Object[newCapacity];
        System.arraycopy(elements,p,a,0,r);
        System.arraycopy(elements,0,a,r,p);
        elements = a;
        head = 0;
        tail = n;
    }

    @Override
    public void push(E e) {
        if (e == null){
            throw new NullPointerException();
        }
        elements[head = (head - 1) & (elements.length - 1)] = e;
        logger.info("push.index head:{}",head);
        if (head == tail){
            doubleCapacity();
        }
    }

    @Override
    public E pop() {
        int h = head;
        @SuppressWarnings("unchecked")
        E result = (E) elements[h];
        if (result == null){
            return null;
        }
        elements[h] = null;
        head = (h + 1) & (elements.length - 1);
        logger.info("pop.index {} = {} & {}",head,Integer.toBinaryString(h + 1),Integer.toBinaryString(elements.length - 1));
        return result;
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }
}
